package com.event.management.frontend.service.impl;

import com.event.management.frontend.domain.QuestionnaireAnswer;
import com.event.management.frontend.domain.QuestionnaireQuestion;
import com.event.management.frontend.domain.QuestionnaireTemplate;
import com.event.management.frontend.domain.UserTicket;
import com.event.management.frontend.dto.QuestionnaireDTO;
import com.event.management.frontend.dto.QuestionnaireAnswerDTO;
import com.event.management.frontend.mapper.EventQuestionnaireMapper;
import com.event.management.frontend.mapper.QuestionnaireAnswerMapper;
import com.event.management.frontend.mapper.QuestionnaireQuestionMapper;
import com.event.management.frontend.mapper.QuestionnaireTemplateMapper;
import com.event.management.frontend.mapper.UserTicketMapper;
import com.event.management.frontend.service.QuestionnaireService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 问卷服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class QuestionnaireServiceImpl implements QuestionnaireService {

    private final EventQuestionnaireMapper eventQuestionnaireMapper;
    private final QuestionnaireTemplateMapper templateMapper;
    private final QuestionnaireQuestionMapper questionMapper;
    private final QuestionnaireAnswerMapper answerMapper;
    private final UserTicketMapper userTicketMapper;
    private final ObjectMapper objectMapper;
    
    @Override
    public QuestionnaireDTO getRandomQuestionnaireByEventId(Long eventId) {
        // 1. 获取活动关联的所有问卷模板ID
        List<Long> templateIds = eventQuestionnaireMapper.selectTemplateIdsByEventId(eventId);
        
        // 如果没有关联问卷，返回null
        if (CollectionUtils.isEmpty(templateIds)) {
            log.info("活动[{}]没有关联的问卷", eventId);
            return null;
        }
        
        // 2. 随机选择一个模板ID
        Long templateId = getRandomElement(templateIds);
        log.info("活动[{}]随机选择问卷模板: {}", eventId, templateId);
        
        // 3. 获取问卷模板信息
        QuestionnaireTemplate template = templateMapper.selectById(templateId);
        if (template == null) {
            log.error("找不到问卷模板: {}", templateId);
            return null;
        }
        
        // 4. 获取问卷问题
        List<QuestionnaireQuestion> questions = questionMapper.selectByTemplateId(templateId);
        
        // 5. 构建问卷DTO
        return buildQuestionnaireDTO(template, questions);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveQuestionnaireAnswer(Long userId, QuestionnaireAnswerDTO answerDTO) {
        try {
            // 1. 验证用户电子票是否属于该用户
            UserTicket userTicket = userTicketMapper.selectById(answerDTO.getUserTicketId());
            if (userTicket == null || !userTicket.getUserId().equals(userId) || !userTicket.getEventId().equals(answerDTO.getEventId())) {
                log.error("用户电子票验证失败: userId={}, ticketId={}, eventId={}", userId, answerDTO.getUserTicketId(), answerDTO.getEventId());
                return false;
            }
            
            // 2. 检查是否已提交过该问卷
            int exists = answerMapper.checkAnswerExists(userId, answerDTO.getEventId(), answerDTO.getUserTicketId());
            if (exists > 0) {
                log.warn("用户已提交过问卷: userId={}, eventId={}, ticketId={}", userId, answerDTO.getEventId(), answerDTO.getUserTicketId());
                return false;
            }
            
            // 3. 构建问卷答案Map
            Map<String, Object> answersMap = new HashMap<>();
            for (QuestionnaireAnswerDTO.QuestionAnswerDTO answer : answerDTO.getAnswers()) {
                answersMap.put(answer.getQuestionId().toString(), answer.getAnswerValue());
            }
            
            // 4. 保存问卷答案
            QuestionnaireAnswer answerEntity = new QuestionnaireAnswer();
            answerEntity.setEventId(answerDTO.getEventId());
            answerEntity.setUserId(userId);
            answerEntity.setTicketId(answerDTO.getUserTicketId());
            answerEntity.setTemplateId(answerDTO.getQuestionnaireId());
            answerEntity.setAnswersJson(objectMapper.writeValueAsString(answersMap));
            answerEntity.setSubmittedAt(new Date());
            
            answerMapper.insert(answerEntity);
            
            // 5. 更新电子票的问卷回答状态
            answerMapper.updateTicketQuestionnaireStatus(answerDTO.getUserTicketId());
            
            log.info("用户问卷答案保存成功: userId={}, eventId={}, ticketId={}", userId, answerDTO.getEventId(), answerDTO.getUserTicketId());
            return true;
        } catch (Exception e) {
            log.error("保存问卷答案失败", e);
            throw new RuntimeException("保存问卷答案失败", e);
        }
    }
    
    /**
     * 从列表中随机选择一个元素
     */
    private <T> T getRandomElement(List<T> list) {
        Random random = new Random();
        return list.get(random.nextInt(list.size()));
    }
    
    /**
     * 构建问卷DTO
     */
    private QuestionnaireDTO buildQuestionnaireDTO(QuestionnaireTemplate template, List<QuestionnaireQuestion> questions) {
        QuestionnaireDTO dto = new QuestionnaireDTO();
        dto.setId(template.getId());
        dto.setTitle(template.getTitle());
        dto.setDescription(template.getDescription());
        
        if (!CollectionUtils.isEmpty(questions)) {
            List<QuestionnaireDTO.QuestionDTO> questionDTOs = questions.stream()
                    .map(q -> {
                        QuestionnaireDTO.QuestionDTO questionDTO = new QuestionnaireDTO.QuestionDTO();
                        questionDTO.setId(q.getId());
                        questionDTO.setQuestionText(q.getQuestionText());
                        questionDTO.setQuestionType(q.getQuestionType());
                        questionDTO.setIsRequired(q.getIsRequired());
                        questionDTO.setSortOrder(q.getSortOrder());
                        
                        // 解析选项JSON
                        questionDTO.setOptions(parseOptions(q.getOptionsJson()));
                        
                        return questionDTO;
                    })
                    .collect(Collectors.toList());
            
            dto.setQuestions(questionDTOs);
        } else {
            dto.setQuestions(Collections.emptyList());
        }
        
        return dto;
    }
    
    /**
     * 解析选项JSON
     */
    private List<QuestionnaireDTO.OptionDTO> parseOptions(String optionsJson) {
        if (optionsJson == null || optionsJson.isEmpty()) {
            return Collections.emptyList();
        }
        
        try {
            // 尝试解析为对象数组格式
            try {
                List<Map<String, String>> options = objectMapper.readValue(
                        optionsJson, new TypeReference<List<Map<String, String>>>() {});
                
                return options.stream()
                        .map(opt -> {
                            QuestionnaireDTO.OptionDTO optionDTO = new QuestionnaireDTO.OptionDTO();
                            optionDTO.setValue(opt.get("value"));
                            optionDTO.setLabel(opt.get("label"));
                            return optionDTO;
                        })
                        .collect(Collectors.toList());
            } catch (JsonProcessingException e) {
                // 如果解析对象数组失败，尝试解析为简单字符串数组
                log.info("尝试解析为简单字符串数组: {}", optionsJson);
                List<String> stringOptions = objectMapper.readValue(
                        optionsJson, new TypeReference<List<String>>() {});
                
                return stringOptions.stream()
                        .map(opt -> {
                            QuestionnaireDTO.OptionDTO optionDTO = new QuestionnaireDTO.OptionDTO();
                            optionDTO.setValue(opt);
                            optionDTO.setLabel(opt);
                            return optionDTO;
                        })
                        .collect(Collectors.toList());
            }
        } catch (JsonProcessingException e) {
            log.error("解析选项JSON失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
} 